package com.google.code.task;

import static com.google.code.task.RetryFailoverDecorator.*;
import static com.google.code.task.TaskResultType.SUCCESS;
import static com.google.code.task.TryCatchDecorator.*;

public class Style {
  public static RetryFailoverDecorator retryFailOver(Task task) {
    return retryFailOver(task, null, DEFAULT_RETRYCOUNT, SUCCESS);
  }

  public static RetryFailoverDecorator retryFailOver(Task task, Task failover) {
    return retryFailOver(task, failover, DEFAULT_RETRYCOUNT, SUCCESS);
  }

  public static RetryFailoverDecorator retryFailOver(Task task, Task failover,
      TaskResultType expected) {
    return retryFailOver(task, failover, DEFAULT_RETRYCOUNT, expected);
  }

  public static RetryFailoverDecorator retryFailOver(Task task, Task failover,
      int retryCount) {
    return retryFailOver(task, failover, retryCount, SUCCESS);
  }

  public static RetryFailoverDecorator retryFailOver(Task task,
      TaskResultType expected) {
    return retryFailOver(task, null, DEFAULT_RETRYCOUNT, expected);
  }

  public static RetryFailoverDecorator retryFailOver(Task task, Task failover,
      int retryCount, TaskResultType expected) {
    return new RetryFailoverDecorator(task).failover(failover).retryCount(
        retryCount).expected(expected);
  }

  public static Task task(Task task) {
    return task;
  }

  public static Task failover(Task task) {
    return task;
  }

  public static int retryCount(int retryCount) {
    return retryCount;
  }

  public static TaskResultType expected(TaskResultType expected) {
    return expected;
  }

  public static AspectDecorator aspect(Task before, Task task, Task after) {
    return new AspectDecorator(task).before(before).after(after);
  }

  public static AspectDecorator nothing() {
    return null;
  }

  public static Task afterTask(Task task) {
    return task;
  }

  public static Task mainTask(Task task) {
    return task;
  }

  public static Task beforeTask(Task task) {
    return task;
  }

  public static AsyncerDecorator asyncer(Task task, TaskEvent event) {
    return new AsyncerDecorator(task).event(event);
  }

  public static AsyncerDecorator asyncer(Task task) {
    return asyncer(task, null);
  }

  public static TaskEvent event(TaskEvent event) {
    return event;
  }

  public static TryCatchDecorator tryCatch(Task task, boolean loggable, boolean throwable,
      TaskResultType resultWhenFailed) {
    return 
      new TryCatchDecorator(task)
        .loggable(loggable)
        .throwable(throwable)
        .resultWhenFailed(resultWhenFailed);
  }

  public static TryCatchDecorator tryCatch(Task task, boolean loggable) {
    return tryCatch(task, loggable, DEFAULT_THROWABLE, DEFAULT_RESULT_WHEN_FAILED);
  }

  public static TryCatchDecorator throwableTryCatch(Task task, boolean loggable) {
    return tryCatch(task, loggable, true, DEFAULT_RESULT_WHEN_FAILED);
  }
  
  public static TryCatchDecorator tryCatch(Task task, TaskResultType resultWhenFailed) {
    return tryCatch(task, DEFAULT_LOGGABLE, DEFAULT_THROWABLE, resultWhenFailed);
  }

  public static TryCatchDecorator throwableTryCatch(Task task, TaskResultType resultWhenFailed) {
    return tryCatch(task, DEFAULT_LOGGABLE, true, resultWhenFailed);
  }

  public static boolean loggable(boolean loggable) {
    return loggable;
  }

  public static boolean throwable(boolean throwable) {
    return throwable;
  }

  public static TaskResultType resultWhenFailed(TaskResultType resultType) {
    return resultType;
  }
  
  public static void startTask() {
    TaskContext.startNewContext();
  }

  public static void startAsyncerTaskProcessor() {
    AsyncerDecorator.startup();
  }

  public static void endTask() {
    TaskContext.endCurrentContext();
  }
  
  public static void endAsyncerTaskProcessor() {
    AsyncerDecorator.shutdown();
  }

  public static TaskChain chain(Task... tasks) {
    TaskChain result = new TaskChain();
    for (Task each : tasks) {
      result.add(each);
    }
    return result;
  }
}
